﻿/***************************************************************
 * 开发人员：网魂小兵@http://www.mozlite.com
 * 
 *  可扩展属性对象基类，数据库保存默认列命名为“Extensions”。
 * 
 * 最后修改：2011-10-19
 * ************************************************************/
namespace Mozlite
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Data;
    using System.Xml.Serialization;

    /// <summary>
    /// 可扩展属性对象基类。
    /// </summary>
    [Serializable]
    public abstract class BaseObject
    {
        /// <summary>
        /// 初始化<see cref="T:Mozlite.BaseObject"/>类。
        /// </summary>
        protected BaseObject() { }

        /// <summary>
        /// 从数据库中加载数据。
        /// </summary>
        /// <param name="reader">数据库读取器。</param>
        protected abstract void Load(IDataReader reader);

        /// <summary>
        /// 从数据库中加载数据。
        /// 自动从数据库中加载扩展列数据。
        /// </summary>
        /// <param name="reader">数据库读取器。</param>
        public void LoadFromDataReader(IDataReader reader) {
            Load(reader);
            CommonHelper.ConvertToObject(reader.GetString(ExtendFieldName), objects);
        }

        /// <summary>
        /// 获取数据库保存扩展属性的列名称。
        /// </summary>
        [XmlIgnore]
        protected virtual string ExtendFieldName {
            get {
                return "Extensions";
            }
        }
       
        /// <summary>
        /// 将字符串装换为对象。
        /// </summary>
        /// <param name="extensions">扩展字符串。</param>
        protected void SetSerializer(string extensions)
        {
            CommonHelper.ConvertToObject(extensions, objects);
        }

        private Dictionary<string, object> objects = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
       
        /// <summary>
        /// 获取本类对象的属性值。
        /// </summary>
        /// <param name="propertyName">属性名称。</param>
        /// <returns>返回该属性的值。</returns>
        public object this[string propertyName]
        {
            get
            {
                object value;
                if (objects.TryGetValue(propertyName, out value))
                    return value;
                return null;
            }
        }

        /// <summary>
        /// 将扩展的属性格式化为字符串。
        /// </summary>
        /// <returns>返回格式化后的字符串。</returns>
        public override string ToString()
        {
            return CommonHelper.ConvertToString(objects);
        }

        /// <summary>
        /// 获取特定属性的值。
        /// </summary>
        /// <typeparam name="T">属性类型。</typeparam>
        /// <param name="propertyName">属性名称。</param>
        /// <param name="defaultValue">默认值。</param>
        /// <returns>返回特定属性的值。</returns>
        public T Get<T>(string propertyName, T defaultValue = default(T))
        {
            object value = this[propertyName];
            if (value == null)
                return defaultValue;
            return value.ChangeTo<T>(defaultValue);
        }

        /// <summary>
        /// 设置扩展属性值。
        /// </summary>
        /// <param name="propertyName">属性名称。</param>
        /// <param name="propertyValue">属性值。</param>
        public void Set(string propertyName, object propertyValue)
        {
            if (objects.ContainsKey(propertyName))
            {
                if (propertyValue == null)
                    objects.Remove(propertyName);
                else
                    objects[propertyName] = propertyValue;
            }
            else
            {
                if (propertyValue != null)
                    objects.Add(propertyName, propertyValue);
            }
        }

        /// <summary>
        /// 判断是否包含属性。
        /// </summary>
        /// <param name="propertyName">属性名称。</param>
        /// <returns>如果保护此属性，返回<c>true</c>。</returns>
        public bool ContainKey(string propertyName)
        {
            return objects.ContainsKey(propertyName);
        }

        /// <summary>
        /// 获取当前属性的字符串值。
        /// </summary>
        /// <param name="propertyName">属性名称。</param>
        /// <returns>返回当前属性的字符串值。</returns>
        public string Get(string propertyName)
        {
            object value = this[propertyName];
            if (value == null)
                return null;
            if (value.GetType().IsEnum)
                return ((int)value).ToString();
            return value.ToString();
        }

        /// <summary>
        /// 将扩展属性进行叠加。
        /// </summary>
        /// <param name="obj">叠加的类型。</param>
        /// <param name="ignoreSelf">是否忽略自身的属性，如果忽略自身属性，则全部取自目标属性进行叠加；否则如果已经包含当前属性，则忽略叠加对象属性。</param>
        public void Merger(BaseObject obj, bool ignoreSelf = false)
        {
            foreach (var kv in obj.objects)
            {
                if ((ignoreSelf && kv.Value != null) || !objects.ContainsKey(kv.Key))
                    Set(kv.Key, kv.Value);
            }
        }

        /// <summary>
        /// 拷贝对象扩展属性。
        /// </summary>
        /// <param name="obj">对象实例。</param>
        public void Copy(BaseObject obj)
        {
            objects.Clear();
            foreach (var kv in obj.objects)
            {
                objects.Add(kv.Key, kv.Value);
            }
        }

        /// <summary>
        /// 获取或设置扩展项数。
        /// </summary>
        public int Count { get { return objects.Count; } }

        /// <summary>
        /// 获取扩展属性键集合。
        /// </summary>
        [XmlIgnore]
        public Dictionary<string, object>.KeyCollection Keys {
            get { return objects.Keys; }
        }
    }
}
